package com.wxmp.market.zhuli.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wxmp.core.util.HttpClientUtils;
import com.wxmp.core.util.StringUtil;
import com.wxmp.core.util.posterUtils;
import com.wxmp.market.zhuli.domain.*;
import com.wxmp.market.zhuli.mapper.WXZhuliJoinDao;
import com.wxmp.market.zhuli.mapper.WxZhuliBaseInfoDao;
import com.wxmp.market.zhuli.mapper.WxZhuliRedeemDao;
import com.wxmp.market.zhuli.mapper.WxZhuliSendDao;
import com.wxmp.market.zhuli.service.impl.*;
import com.wxmp.wxapi.process.MpAccount;
import com.wxmp.wxapi.process.WxApi;
import com.wxmp.wxapi.process.WxApiClient;
import com.wxmp.wxapi.process.WxMemoryCacheClient;
import com.wxmp.wxapi.vo.MsgRequest;
import com.wxmp.wxcms.domain.AccountFans;
import com.wxmp.wxcms.domain.MsgLog;
import com.wxmp.wxcms.domain.MsgNews;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 活动规则执行
 */
@Service("zhuliRulesProcessor")
public class ZhuliRulesProcessor {

    private ExecutorService executor = Executors.newCachedThreadPool();

    private static Logger logger = LogManager.getLogger(HttpClientUtils.class);

    @Autowired
    private WxZhuliBaseInfoServiceImpl baseInfoService;

    @Autowired
    private WxZhuliSendServiceImpl sendService;

    @Autowired
    private WXQRCodeServiceImpl wxqRcodeService;

    @Autowired
    private WxZhuliJoinServiceImpl joinService;

    @Autowired
    private WxZhuliRedeemServiceImpl redeemService;

    /**
     * 活动规则及文案
     */
    private RuleConfig defaultRuleConfig = new RuleConfig();

    public void scanProcessor(MsgRequest msgRequest, MpAccount account) {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    scanActivityByQRCode(msgRequest, account);
                } catch (Exception e) {
                    throw new RuntimeException("报错啦！！");
                }
            }
        });
    }

    /**
     * 活动入口-扫描二维码
     * 1、根据二维码ID获取对应的发起活动
     * 2、如果为发起活动二维码
     * ***2.1、判断当前活动是否有发起记录
     * ***2.2、有发起记录：提示文案，并判断活动是否已经完成了
     * ***2.3、活动已经完成：发送记录的兑换码/优惠券码 及说明文档和小程序卡券
     * ***2.3、活动还未完成：发送话术及海报图片
     * ***2.4、无发起记录
     * ***2.5、发起活动并记录数据 及生成活动海报并发送话术和海报
     * 3、不是活动发起相关的二维码
     * ***3.1、根据二维码编号，查询已经发起活动的列表，确认是否为扫描朋友发起的，此时则作为助力者身份
     * ***3.2、是，且活动有效，助力未满，当前用户没有其它助力记录：助力成功，发送话术，通知发起者
     * ***3.3、首次助力：默认发起活动，且生成海报，发送文案及海报
     * ***3.4、非首次助力：提示文案
     *
     * @param request 当前用户扫码事件
     * @param account 当前账号信息
     * @return
     */
    public Result scanActivityByQRCode(MsgRequest request, MpAccount account) {
        //request.getFromUserName()
        //1、判断是否有活动
        Result result = new Result();
        //defaultRuleConfig = new RuleConfig();
        try {
            //获取粉丝详细信息
            AccountFans fans = WxApiClient.syncAccountFans(request.getFromUserName(), account);

            //场景值特殊处理
            String[] scenes = request.getEventKey().split("_");
            if (scenes.length > 1)
                request.setEventKey(scenes[1]);
            //判断二维码所属活动是否有效
            Result baseResult = getActivityByQRCode(request.getEventKey());
            if (baseResult.getCode() != 0) {
                //确认是否为活动参与码
                WxZhuliSend send = sendService.selectSendInfoByQRCode(request.getEventKey());
                if (send == null) { //当前扫码没有发起记录
                    //没有活动发起记录，可以不处理，记录日志即可
                    result.setCode(1006);
                    result.setMsg(defaultRuleConfig.getActivity_status_fail());
                    return result;
                } else {
                    //有发起记录，确认当前发起的活动还在有效期
                    Result sendResult = getActivityByBaseCode(send.getBaseCode());
                    if (sendResult.getCode() != 0) {
                        result = sendResult;
                        return result;
                    } else {
                        Result joinResult = joinProcess(request, send, fans, account);
                        if (joinResult.getCode() != 0) {
                            result = joinResult;
                            return result;
                        }
                    }
                }
            } else {
                //发起逻辑 Process
                Result sendResult = sendProcess(request, baseResult.getContent(), fans, account, false);
                if (sendResult.getCode() != 0) { // 发起失败
                    result = sendResult;
                    return result;
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            try {
                WxApiClient.sendCustomTextMessage(request.getFromUserName(), result.getMsg(), account);
            } catch (Exception ex) {
                System.out.printf(ex.getMessage());
            }
            //日志写入
        }
        return null;
    }

    /**
     * 获取活动规则及话术信息
     *
     * @param baseInfo
     */
    private void getActivityRuleConfig(WxZhuliBaseInfo baseInfo) {
        if (null != baseInfo) {
            try {
                //region *****活动规则加载
                RuleConfig currentRuleConfig = WxMemoryCacheClient.getActivityRuleConfig(baseInfo.getBaseCode());
                if (currentRuleConfig == null) {
                    if (StringUtil.isNotEmpty(baseInfo.getBaseRulesConfig()))
                        currentRuleConfig = JSON.parseObject(baseInfo.getBaseRulesConfig(), RuleConfig.class);
                    if (currentRuleConfig != null)
                        WxMemoryCacheClient.addActivityRuleConfig(baseInfo.getBaseCode(), currentRuleConfig);
                } else {
                    defaultRuleConfig = currentRuleConfig;
                }
                //endregion
            } catch (Exception ex) {
                System.out.printf(ex.getMessage());
            }
        }
    }

    /**
     * 根据扫码的二维码编号获取活动配置信息
     * <p>
     * 1、根据二维码值获取活动信息
     * 2、活动信息不存在或状态或不在有效期内，则提示用户：活动无效
     *
     * @param qrCode 扫码值 EventValue
     * @return
     */
    private Result getActivityByQRCode(String qrCode) {
        Result result = new Result();
        Date date = new Date();
        try {
            WxZhuliBaseInfo currentInfo = baseInfoService.selectByQRCode(qrCode);
            if (currentInfo == null) {
                result.setCode(1000);
                result.setMsg(defaultRuleConfig.getActivity_status_fail());
                return result;
            }
            if (currentInfo.getBaseStatus() != 0
                    || currentInfo.getBaseStartTime().getTime() > date.getTime()
                    || currentInfo.getBaseEndTime().getTime() < date.getTime()) {
                result.setCode(1004);//枚举值替换
                result.setMsg(defaultRuleConfig.getActivity_status_fail());
                return result;
            }
            getActivityRuleConfig(currentInfo);
            result.setCode(0);
            result.setMsg("success");
            result.setContent(currentInfo.getBaseCode());
        } catch (Exception ex) {
            System.out.printf(ex.getMessage());
        }
        return result;
    }


    /**
     * 根据活动编号获取活动配置
     *
     * @param baseCode 活动编号
     * @return
     */
    private Result getActivityByBaseCode(String baseCode) {
        Result result = new Result();
        Date date = new Date();
        WxZhuliBaseInfo currentInfo = baseInfoService.selectByBaseCode(baseCode);
        if (currentInfo == null) {
            result.setCode(1000);
            result.setMsg(defaultRuleConfig.getActivity_status_fail());
            return result;
        }
        if (currentInfo.getBaseStatus() != 0
                || currentInfo.getBaseStartTime().getTime() > date.getTime()
                || currentInfo.getBaseEndTime().getTime() < date.getTime()) {
            result.setCode(1004);//枚举值替换
            result.setMsg(defaultRuleConfig.getActivity_status_fail());
            return result;
        }
        getActivityRuleConfig(currentInfo);
        result.setCode(0);
        result.setMsg("success");
        result.setContent(currentInfo.getBaseCode());
        return result;
    }

    /**
     * 活动发起逻辑处理
     *
     * @param request       当前扫码人员
     * @param baseCode      活动编号
     * @param fans          当前扫码人员详细信息（包括昵称、等）
     * @param account       当前公众账号信息
     * @param isCurrentJoin 是否被动发起（参加活动默认发起  true 是  false 否）
     * @return
     */
    private Result sendProcess(MsgRequest request, String baseCode, AccountFans fans, MpAccount account,
                               boolean isCurrentJoin) {
        //活动发起
        /**
         * 1、确认是否有历史发起记录 有：提示
         * 2、发起记录：生成个二维码二维码（临时一个月），生成海报图片
         */
        Result result = new Result();
        HashMap<String, String> map = new HashMap<>();
        map.put("baseCode", baseCode);
        map.put("sendOpenId", request.getFromUserName());
        WxZhuliSend send = sendService.selectSendInfoBySend(map);
        if (send != null) {
            result.setCode(1001);
            result.setMsg(defaultRuleConfig.getActivity_send_limit());
            return result;
        } else {
            //生成二维码
            WXQRCode wxqrCode = wxqRcodeService.getActivityQRCode(request.getFromUserName(), baseCode, account);
            if (wxqrCode != null) {
                //活动模板生成
                String backgroundPath = "C:\\gimborn\\background.jpg";
                String message01 = fans != null ? fans.getNickname() : defaultRuleConfig.getActivity_default_nickname();
                String outPutPath = String.format("%s%s%s", "C:\\gimborn\\poster\\", baseCode + "-" + request.getFromUserName(), ".jpg");
                String outResult = posterUtils.overlapImage(backgroundPath, wxqrCode.getQrPathName(), message01, "", outPutPath);
                if (StringUtil.isBlank(outResult) || !outResult.equalsIgnoreCase("success")) {
                    result.setCode(1002);
                    result.setMsg("您好，活动发起失败，请您重新尝试扫码，如有疑问，请咨询客服");
                    return result;
                }
                //图片上传至微信
                String url = "";
                String media_id = "";
                try {
                    JSONObject jsonObject = WxApiClient.addMateriaTemp(outPutPath, "image", account);
                    if (jsonObject != null) {
                        if (jsonObject.containsKey("url"))
                            url = jsonObject.getString("url"); //图片URL
                        if (jsonObject.containsKey("media_id"))
                            media_id = jsonObject.getString("media_id");
                    }
                } catch (Exception ex) {
                    System.out.println(ex.toString());
                }
                WxZhuliSend zhuliSend = new WxZhuliSend();
                zhuliSend.setBaseCode(baseCode);
                zhuliSend.setSendCode(UUID.randomUUID().toString());
                zhuliSend.setSendOpenid(request.getFromUserName());
                zhuliSend.setSendNickname(fans != null ? fans.getNickname() : defaultRuleConfig.getActivity_default_nickname());
                zhuliSend.setSendQrcode(wxqrCode.getQrSceneId());
                zhuliSend.setSendPosterMediaid(media_id);
                zhuliSend.setSendPosterUrl(url);
                sendService.add(zhuliSend);
                try {
                    if (!isCurrentJoin)
                        WxApiClient.sendCustomTextMessage(request.getFromUserName(),
                                String.format(defaultRuleConfig.getActivity_send_success(), fans != null ? fans.getNickname() : defaultRuleConfig.getActivity_default_nickname()),
                                account);
                    WxApiClient.sendCustomImageMessage(request.getFromUserName(), media_id, account);
                    WxApiClient.sendCustomMiniApp(request.getFromUserName(),
                            defaultRuleConfig.getActivity_success_redeem_miniapp_appid(),
                            defaultRuleConfig.getActivity_success_redeem_miniapp_path(),
                            defaultRuleConfig.getActivity_success_redeem_miniapp_title(),
                            defaultRuleConfig.getActivity_success_redeem_miniapp_thumb_media_id(), account);
                } catch (Exception ex) {
                    System.out.printf(ex.getMessage());
                }
                //发送图片素材ID
                result.setCode(0);
                result.setMsg("success");
                return result;
            }
        }
        return null;
    }

    /**
     * 活动参与逻辑
     *
     * @return
     */
    private Result joinProcess(MsgRequest request, WxZhuliSend send, AccountFans fans, MpAccount account) {
        Result result = new Result();
        int currentJoinCount = 0;
        //有效性校验
        //1 确认当前账号是否已经参与过当前团
        //2 确认当前账号是否参加过其它团
        //3 确认当前助力的团还未完成（可参与）
        if (send.getSendStatus() == 1) {
            //活动发起
            sendProcess(request, send.getBaseCode(), fans, account, true); //默认发起
            result.setCode(1001);
            result.setMsg(defaultRuleConfig.getActivity_join_full_limit());
            //发起活动
            return result;
        }
        //当前团的发起人为自己，不能为自己助力
        if (send.getSendOpenid().equalsIgnoreCase(request.getFromUserName())) {
            result.setCode(1000);
            result.setMsg(defaultRuleConfig.getActivity_join_this_limit());
            //不能为自己助力
            return result;
        }
        //是否为当前好友助过力过
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("baseCode", send.getBaseCode());
        map.put("sendCode", send.getSendCode());
        List<WxZhuliJoin> joins = joinService.selectJoinInfoBySendCode(map);
        if (joins != null) {
            currentJoinCount = joins.size(); //当前已经助力的人数
            for (WxZhuliJoin join : joins) {
                if (join.getJoinOpenid().equalsIgnoreCase(request.getFromUserName())) {
                    result.setCode(1002);
                    result.setMsg(defaultRuleConfig.getActivity_join_joined_limit());
                    return result;
                }
            }
        }
        //同一个活动下，是否为其它好友助力过
        HashMap<String, String> map2 = new HashMap<String, String>();
        map2.put("baseCode", send.getBaseCode());
        map2.put("joinOpenId", request.getFromUserName());
        WxZhuliJoin join2 = joinService.selectJoinInfoByOpenId(map2);
        if (join2 != null) {
            result.setCode(1002);
            result.setMsg(defaultRuleConfig.getActivity_join_others_limit());
            return result;
        }
        //判断是否为新关注才能助力
        if (request.getEvent().equalsIgnoreCase("scan")) {
            //活动发起
            sendProcess(request, send.getBaseCode(), fans, account, true); //默认发起
            result.setCode(1003);
            result.setMsg(defaultRuleConfig.getActivity_join_join_scan_limit());
            return result;
        }

        //执行助力行为
        Lock lock = new ReentrantLock();
        try {
            WxZhuliJoin joinInfo = new WxZhuliJoin();
            joinInfo.setBaseCode(send.getBaseCode());
            joinInfo.setSendCode(send.getSendCode());
            joinInfo.setJoinNickname(fans != null ? fans.getNickname() : defaultRuleConfig.getActivity_default_nickname());
            joinInfo.setJoinOpenid(request.getFromUserName());
            joinInfo.setJoinQRCode(request.getEventKey());
            /**
             * 活动参与数据写入
             * 1、需要确定参与人数，同步执行
             * 2、助力成功后：如果助力人数已满，则此次助力活动已完成
             * 3、活动完成：通知活动发起人活动完成并推送兑换券码
             */
            //加锁
            lock.lock();
            //查询当前活动发起状态是否为已完成（防止并发状态数据窜）
            send = sendService.selectSendInfoByQRCode(request.getEventKey());
            if (send == null || send.getSendStatus() == 1) {
                result.setCode(1005);
                result.setMsg(defaultRuleConfig.getActivity_join_joined_limit());
                return result;
            }
            //助力数据写入
            joinService.add(joinInfo);
            //当前助力人数
            currentJoinCount++;
            //如果助力人数已满足活动规则
            if (currentJoinCount >= 5) //暂定为5个参与人数
            {
                //更改发起活动的状态为已完成
                sendService.sendDone(send);
                //更改当前发起状态为已完成2
                lock.unlock();
                //发送完成信息
                sendDone(send, joinInfo, account, request, fans);
            } else
                joinSuccess(request, send, joinInfo, fans, account);
        } catch (Exception ex) {
            System.out.printf(ex.getMessage());
        } finally {
            if (((ReentrantLock) lock).isLocked())
                lock.unlock();
        }
        result.setCode(0);
        result.setMsg("success");
        return result;
    }

    /**
     * 当前发起的助力活动已经完成（满足）
     */
    private void sendDone(WxZhuliSend send, WxZhuliJoin join, MpAccount account, MsgRequest request, AccountFans fans) {
        //微信通知已完成
        Lock lock = new ReentrantLock();
        String textMsg = "";
        String miniAppLink = WxApi.getTextMiniAppUrl(defaultRuleConfig.getActivity_success_redeem_miniapp_appid(),
                defaultRuleConfig.getActivity_success_redeem_miniapp_path(), "点击去兑换");
        boolean isSuccess = false;
        try {
            //获取一个兑换码
            lock.lock();
            WxZhuliRedeem redeem = redeemService.selectAvailableCode(send.getBaseCode());
            if (redeem != null) {
                redeem.setRedeemStatus(1);
                redeem.setRedeemSendTime(new Date());
                redeem.setRedeemOpenid(send.getSendOpenid());
                redeemService.updateAvailableCode(redeem);
                isSuccess = true;
                //miniAppLink=
                textMsg = String.format(defaultRuleConfig.getActivity_send_join_full_redeem_success(), join.getJoinNickname(), redeem.getRedeemCode(), miniAppLink);
                lock.unlock();
                //领取成功
            } else {
                //兑换码以已用完了 发送优惠券
                isSuccess = true;
                textMsg = String.format(defaultRuleConfig.getActivity_send_join_full_coupon_success(), join.getJoinNickname(), "test", miniAppLink);
            }
        } catch (Exception ex) {
            System.out.printf(ex.getMessage());

        } finally {
            if (((ReentrantLock) lock).isLocked())
                lock.unlock();
            try {
                if (isSuccess) {
                    //兑换码推送 （活动发起者）
                    WxApiClient.sendCustomTextMessage(send.getSendOpenid(), textMsg, account);
                    //参与成功推送 （活动助力者）
                    WxApiClient.sendCustomTextMessage(join.getJoinOpenid(), defaultRuleConfig.getActivity_join_success(), account);
                    //发送兑换说明素材图片
                    if (StringUtil.isNotEmpty(defaultRuleConfig.getActivity_success_redeem_explain_mediaid())) {
                        MsgNews news = new MsgNews();
                        news.setMediaId(defaultRuleConfig.getActivity_success_redeem_explain_mediaid());
                        WxApiClient.sendCustomNews(send.getSendOpenid(), news, account);
                    }
                    //当前助力者默认发起活动
                    Result result = sendProcess(request, send.getBaseCode(), fans, account, true);
                    if (result.getCode() != 0) {
                        //日志写入
                    }
                    //删除素材信息（素材库数量有限，完成活动删除素材信息）
                    WxApiClient.deleteMaterial(send.getSendPosterMediaid(), account);
                }
            } catch (Exception ex) {
                System.out.printf(ex.getMessage());
            }
        }
    }

    /**
     * 参与助力成功
     *
     * @param send
     * @param join
     * @param account
     */
    private void joinSuccess(MsgRequest request, WxZhuliSend send, WxZhuliJoin join, AccountFans fans, MpAccount
            account) {
        try {
            //微信通知发起者有人参与
            WxApiClient.sendCustomTextMessage(send.getSendOpenid(), String.format(defaultRuleConfig.getActivity_send_join_success(), join.getJoinNickname()), account);
            //微信通知参与者，参与成功
            WxApiClient.sendCustomTextMessage(join.getJoinOpenid(), String.format(defaultRuleConfig.getActivity_join_success()), account);
            //当前助力者默认发起活动
            Result result = sendProcess(request, send.getBaseCode(), fans, account, true);
            if (result.getCode() != 0) {
                //日志写入
            }
        } catch (Exception ex) {
            System.out.printf(ex.getMessage());
        }
    }
}
